package com.runa.persistence.check;

import com.runa.monitor.comm.dto.newComm.AsynResult;
import com.runa.monitor.comm.entity.CommNetEquipment;
import com.runa.persistence.DateUtil;
import lombok.Data;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 2024/7/4 9:16
 * zhangYB
 */
@Data
public class DownTask {


    private String taskId;

    private Integer priority;

    private List<String> equList;

    private Integer equCount;

    private Integer finishCount = 0;

    private AtomicInteger queryEquCount = new AtomicInteger(0);

    private Map<String, DownTaskNetEquip> netEquMap = new ConcurrentHashMap<>();

    private String taskTime;
    private String taskTimeRecord = "";

    private AtomicInteger queueCount = new AtomicInteger(0);
    private AtomicInteger downCount = new AtomicInteger(0);

    private AtomicInteger protocolNotMatchCount = new AtomicInteger(0);

    private AtomicInteger upPendingCount = new AtomicInteger(0);
    private AtomicInteger upSuccessCount = new AtomicInteger(0);
    private AtomicInteger upFailedCount = new AtomicInteger(0);

    public static DownTask initDownTask(String taskId, Integer priority, List<String> netEquList) {
        return new DownTask(taskId, priority, netEquList);
    }

    private DownTask(String taskId, Integer priority, List<String> netEquList) {
        this.taskId = taskId;
        this.priority = priority;
        this.equList = netEquList;
        if (null != netEquList) {
            this.equCount = netEquList.size();
        }
        taskTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:sss").format(new Date());
    }

    private void increase(AtomicInteger count) {
        increase(count, 1);
    }

    private void increase(AtomicInteger count, int size) {
        if (null == count) {
            return;
        }
        int oldCount = count.get();
        while (!count.compareAndSet(oldCount, oldCount+size)) {
            oldCount = count.get();
        }
    }


    public void queueCount(String netEquSerial, int size) {
        increase(queueCount, size);
        if (null == netEquSerial) {
            return;
        }
        DownTaskNetEquip downTaskNetEquip = netEquMap.get(netEquSerial);
        if (null == downTaskNetEquip) {
            return;
        }
        downTaskNetEquip.queueCount(size);
    }


    public void protocolNotMatch(String netSerial, int size) {
        increase(protocolNotMatchCount, size);
    }

    public void failedUpCount(String netEquSerial) {
        increase(upFailedCount);
        if (null == netEquSerial) {
            return;
        }
        DownTaskNetEquip downTaskNetEquip = netEquMap.get(netEquSerial);
        if (null == downTaskNetEquip) {
            return;
        }
        downTaskNetEquip.failedUpCount();
    }

    public void successUpCount(String netEquSerial) {
        increase(upSuccessCount);
        if (null == netEquSerial) {
            return;
        }
        DownTaskNetEquip downTaskNetEquip = netEquMap.get(netEquSerial);
        if (null == downTaskNetEquip) {
            return;
        }
        downTaskNetEquip.successUpCount();
    }


    private AtomicInteger successCount = new AtomicInteger(0);
    private AtomicInteger failedCount = new AtomicInteger(0);

    public void result(AsynResult asynResult) {
        boolean b = asynResult.getCode() == 200;
        if (b) {
            increase(successCount);
        } else {
            increase(failedCount);
        }
        String netEquSerial = asynResult.getId();
        if (null == netEquSerial) {
            return;
        }
        DownTaskNetEquip downTaskNetEquip = netEquMap.get(netEquSerial);
        if (null == downTaskNetEquip) {
            return;
        }
        downTaskNetEquip.result(b);
    }

    public void pendingUpCount(String netEquSerial) {
        increase(upPendingCount);
        if (null == netEquSerial) {
            return;
        }
        DownTaskNetEquip downTaskNetEquip = netEquMap.get(netEquSerial);
        if (null == downTaskNetEquip) {
            return;
        }
        downTaskNetEquip.pendingUpCount();
    }

    public void downCount(String netEquSerial, int size) {
        increase(downCount, size);
        if (null == netEquSerial) {
            return;
        }
        DownTaskNetEquip downTaskNetEquip = netEquMap.get(netEquSerial);
        if (null == downTaskNetEquip) {
            return;
        }
        downTaskNetEquip.downCount(size);
    }

    public void increaseQueryEquCount(int size) {
        int oldCount = queryEquCount.get();
        while (!queryEquCount.compareAndSet(oldCount, oldCount+size)) {
            oldCount = queryEquCount.get();
        }
    }

    public void downTaskNetEquip(List<CommNetEquipment> commNetEquipmentList) {
        if (null == commNetEquipmentList && commNetEquipmentList.isEmpty()) {
            return;
        }
        for (CommNetEquipment commNetEquipment : commNetEquipmentList) {
            DownTaskNetEquip downTaskNetEquip = new DownTaskNetEquip();
            downTaskNetEquip.setId(commNetEquipment.getId());
            downTaskNetEquip.setSerial(commNetEquipment.getSerial());
            int size = commNetEquipment.getNodeList().size();
            downTaskNetEquip.addEquCount(size);
            downTaskNetEquip.setType(commNetEquipment.getType());
            netEquMap.put(commNetEquipment.getSerial(), downTaskNetEquip);
            increaseQueryEquCount(size);
        }
    }

    public String getTaskTimeRecord() {
        int i = upSuccessCount.get() + upFailedCount.get();
        if (finishCount < i) {
            finishCount = i;
            taskTimeRecord += String.format(" [%s: %s 条] ", DateUtil.timeNow(), finishCount);
        }
        return taskTimeRecord;
    }

    @Override
    public String toString() {
        return
                "任务时间=" + taskTime +
                ", 设备=" + equCount +
                ", 优先级=" + priority +
                ", 查询设备=" + queryEquCount +
                ", 入队=" + queueCount +
                ", 下发=" + downCount +
                ", 协议未匹配=" + protocolNotMatchCount +
                ", 待上报=" + upPendingCount +
                ", 成功数量=" + successCount +
                ", 失败数量=" + failedCount +
                ", 上报成功=" + upSuccessCount +
                ", 上报失败=" + upFailedCount +
                ", 网络设备" + netEquMap.size();
    }

    public boolean finished() {
        return finishCount==equCount || DateUtil.beyondOneHour(taskTime);
    }


}
